class Part
  attr_reader :atom;
  
  def initialize(atom)
    @atom = atom;
  end

end

class Eletron < Part
  attr_reader :layer;
  Levels = {:s => 1, :p => 2, :d => 3, :f => 4};
  
  def initialize(atom, layer, level)
    super(atom);
    @layer = layer;
    self.level = level
  end
  
  def level=(level)
    type = level.class
    @level = ([String, Symbol].include?(type)) ? self.class::Levels[level.to_sym] : level;
  end
  
  def level
    self.class::Levels.index @level
  end
  
end

class Proton < Part
end

class Neutron < Part
end

class Atom
  attr_reader :protons, :eletrons, :neutrons;

  def initialize(protons, neutrons, eletrons=protons)
    create = lambda{|n, klass, *a| Array.new(n, klass.new(*a)).map{|o| o.dup}}
    @protons = create.call(protons, Proton, self)
    @neutrons = create.call(neutrons, Neutron, self)
    @eletrons = create.call(eletrons, Eletron, self, 2, 2)
  end

end

puts Atom.new(10,20).protons.inspect